import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
// import { VerticalDiffManager } from '../../../src/diff/vertical/VerticalDiffManager';
import { LLMFactory } from '../../../core/llm/llmFactory';
import { BaseLLM } from '../../../core/llm/baseLLM';
import { ProxyService } from '../../../src/services/proxyService';
import { checkLoginStatus } from '../../utils/authGuard';
import { AnalyticsService } from '../../../src/services/analyticsService';
import { Logger } from '../../../src/logger/Logger';

// 导入实体类型
import { FunctionInfo, BaseCommonCppContext, HarmonyCppPromptContext, DefsInFunc } from './entities/types';

// 导入处理器
import { CxxElementExtractor } from './processors/CxxElementExtractor';
import { ClassifyDefinitionsProcessor } from './processors/ClassifyDefinitionsProcessor';
import { CxxCustomizationProcessor } from './processors/CxxCustomizationProcessor';
import { OtherProcessor } from './processors/OtherProcessor';
import { FunctionCodeProcessor } from './processors/FunctionCodeProcessor';
import { FuncBasicInfoProcessor } from './processors/FuncBasicInfoProcessor';
import { HarmonyBranchMapProcessor } from './processors/HarmonyBranchMapProcessor';
import { StaticMethod } from './processors/StaticMethod';
import { TemplateMethod } from './processors/TemplateMethod';

// 导入工具函数
import { waitForTimeout } from './utils/utils';
import { TreeSitter } from '../../../core/treesitter/TreeSitter';

// 常量定义
const HARMONY_TIMEOUT_MS = 30000;
const RESERVE_TIME_MS = 200;

export class UnitTestGenerator {
    
    /**
     * 终端DT C++定制化方法
     * @param document 文档对象
     * @param position 位置
     * @param unittestsDir 单元测试目录
     * @param utcoreTimeout 超时时间
     * @returns 提示上下文对象
     */
    public static async terminalDTCxxCustomization(
        document: vscode.TextDocument,
        position: vscode.Position,
        unittestsDir: string,
        utcoreTimeout: number
    ): Promise<Object | null> {
        Logger.info(`terminalDTCxxCustomization start.`);
        await TreeSitter.getInstance().init();
        const start = Date.now(); // 记录开始时间
        const res = await this.parseHarmonyTaskParameter(document, position, unittestsDir, utcoreTimeout) as HarmonyCppPromptContext | null;
        const end = Date.now(); // 记录结束时间
        const executionTime = end - start; // 计算执行时间
        TreeSitter.getInstance().clearCache();
        Logger.info(`terminalDTCxxCustomization time cost: ${executionTime}ms.result: ${JSON.stringify(res)}`);
        return res;
    }

    /**
     * 解析Harmony任务参数
     * @param document 文档对象
     * @param position 位置
     * @param unittestsDir 单元测试目录
     * @param utcoreTimeout 超时时间
     * @returns 提示上下文对象
     */
    public static async parseHarmonyTaskParameter(
        document: vscode.TextDocument,
        position: vscode.Position,
        unittestsDir: string,
        utcoreTimeout: number
    ): Promise<Object | null> {
        const start = Date.now(); // 记录开始时间
        const range = OtherProcessor.getFunctionRange(document, position);
        const functionInfo = await FuncBasicInfoProcessor.extract(document, position, range);
        CxxCustomizationProcessor.parseSignature(document, range, functionInfo);
        const commonContext: BaseCommonCppContext = await this.getBaseCommonCppContext(document, functionInfo, range);
        const pathMap = await HarmonyBranchMapProcessor.extract(commonContext.code || "", document.languageId);
        const end = Date.now(); // 记录结束时间
        const executionTime = end - start; // 计算执行时间
        const timeoutMs = (utcoreTimeout || HARMONY_TIMEOUT_MS) - executionTime;
        Logger.info(`parseHarmonyTaskParameter mustContext success time cost: ${executionTime} ms.remianing time: ${timeoutMs} ms`);

        if (timeoutMs <= 0) {
            return await this.getHarmonyDtMustUsePromptContext(document, functionInfo, commonContext, range, pathMap);
        }

        try {
            const promptPromise = this.getHarmonyCppContext(document, functionInfo, commonContext, range, pathMap, position, unittestsDir, timeoutMs);
            const res = await Promise.race([promptPromise, waitForTimeout(timeoutMs || HARMONY_TIMEOUT_MS)]);
            if (!res) {
                return await this.getHarmonyDtMustUsePromptContext(document, functionInfo, commonContext, range, pathMap);
            }
            return res;
        } catch (err) {
            Logger.error(`getHarmonyCppContext This request was aborted because it took more than ${timeoutMs || HARMONY_TIMEOUT_MS} ms`);
            return await this.getHarmonyDtMustUsePromptContext(document, functionInfo, commonContext, range, pathMap);
        }
    }

    /**
     * 获取HarmonyDT必须使用的提示上下文
     * @param document 文档对象
     * @param functionInfo 函数信息
     * @param commonContext 通用上下文
     * @param range 范围
     * @param pathMap 路径映射
     * @returns 提示上下文
     */
    private static async getHarmonyDtMustUsePromptContext(
        document: vscode.TextDocument,
        functionInfo: FunctionInfo,
        commonContext: BaseCommonCppContext,
        range: vscode.Range,
        pathMap: any[]
    ): Promise<HarmonyCppPromptContext | null> {
        const start = Date.now(); // 记录开始时间
        const addRowFunctionCode = HarmonyBranchMapProcessor.addLineNumber(functionInfo.code ?? '');
        const harmonyCppPromptContext: HarmonyCppPromptContext = {
            ...commonContext,
            is_static_method: await StaticMethod.extract(document, range, functionInfo),
            is_template_method: await TemplateMethod.extract(functionInfo),
            callee_method_class: {},
            returnType: '',
            sourceClass: '',
            sourceClassConstructors: {
                public: [],
                protected: [],
                private: []
            },
            sourceClassMembers: [],
            paramDefinitions: [],
            signature: functionInfo.signature || '',
            targetFunctionCode: functionInfo.code || '',
            addRowFunctionCode,
            modulePath: '/harmony' + document.fileName.replace(/^[A-Z]:/i, '').replace(/\\/g, '/'),
            sourceMethodBranchMap: [...pathMap],
            is_harmony_scenario: true,
            gmock_template_str: '',
            cpp_stub_template_str: '',
            funcCalledList: [],
            source_cls_namespace_name: '',
            existing_test_case: [],
            existing_test_suite: '',
            existing_gmock_def: [],
            existing_cpp_stub_def: [],
            interface_definitions: [],
            source_class_constructor_method: '',
            source_class_name_lower: '',
            init_head_macro: '',
            gmock_str: '',
            cppstub_str: '',
            source_class_fields: '',
            include_statement: '',
            using_namespace: '',
            other_str: ''
        };
        const end = Date.now(); // 记录结束时间
        const executionTime = end - start; // 计算执行时间
        Logger.info(`getHarmonyDtMustUsePromptContext success time cost: ${executionTime}ms.`);
        return harmonyCppPromptContext;
    }

    /**
     * 获取Harmony C++上下文
     * @param document 文档对象
     * @param functionInfo 函数信息
     * @param commonContext 通用上下文
     * @param range 范围
     * @param pathMap 路径映射
     * @param position 位置
     * @param unittestsDir 单元测试目录
     * @param utcoreTimeout 超时时间
     * @returns 提示上下文
     */
    private static async getHarmonyCppContext(
        document: vscode.TextDocument,
        functionInfo: FunctionInfo,
        commonContext: BaseCommonCppContext,
        range: vscode.Range,
        pathMap: any[],
        position: vscode.Position,
        unittestsDir: string,
        utcoreTimeout: number
    ): Promise<HarmonyCppPromptContext | null> {
        const start = Date.now(); // 记录开始时间
        try {
            const extractor = new CxxElementExtractor();
            const { symbolDefinitions } = await extractor.getElements({ doc: document, pos: position }, functionInfo);
            await CxxCustomizationProcessor.getSnippetDefinitions(document, range, symbolDefinitions);
            const definitionInFunction: DefsInFunc = await ClassifyDefinitionsProcessor.classifyDefinitions(symbolDefinitions, functionInfo);
            const { templateInstantiation, templateDeclar } = await CxxCustomizationProcessor.getTemplateStatment(document, functionInfo);
            const targetFunctionCode = functionInfo.code ? (`${templateDeclar}\r\n${functionInfo.code}\r\n${templateInstantiation}`) : '';
            const addRowFunctionCode = HarmonyBranchMapProcessor.addLineNumber(targetFunctionCode ?? '');
            const { gmockTemplateStr, cppStubTemplateStr, setFuncCalledList, interfaceDefinitions, allGmock, allCppStub, otherStr } =
                await CxxCustomizationProcessor.handleAllDefinitions(symbolDefinitions, functionInfo, pathMap);
            const { constructorsMethod, classNameLower, gmockStr, cppstubStr, classFields } =
                await CxxCustomizationProcessor.handleSourceMethod(functionInfo, definitionInFunction, allGmock, allCppStub, document.languageId);
            const usingNamespace = CxxCustomizationProcessor.getUsingNamespace(definitionInFunction.others.paramNamespace, definitionInFunction.classNamespace);
            const harmonyCppPromptContext: HarmonyCppPromptContext = {
                ...commonContext,
                is_static_method: await StaticMethod.extract(document, range, functionInfo),
                is_template_method: await TemplateMethod.extract(functionInfo),
                callee_method_class: {},
                returnType: definitionInFunction.return,
                sourceClass: definitionInFunction.class,
                sourceClassConstructors: definitionInFunction.classCtors,
                sourceClassMembers: definitionInFunction.classMembers,
                paramDefinitions: definitionInFunction.parameters.concat(definitionInFunction.others.classCtorsParamDefinition),
                signature: functionInfo.signature || '',
                targetFunctionCode,
                addRowFunctionCode,
                modulePath: '/harmony' + document.fileName.replace(/^[A-Z]:/i, '').replace(/\\/g, '/'),
                sourceMethodBranchMap: [...pathMap],
                is_harmony_scenario: true,
                gmock_template_str: gmockTemplateStr,
                cpp_stub_template_str: cppStubTemplateStr,
                funcCalledList: setFuncCalledList,
                source_cls_namespace_name: `${(definitionInFunction.classNamespace && usingNamespace) ?
                    definitionInFunction.classNamespace + ';' : definitionInFunction.classNamespace}${usingNamespace}`,
                existing_test_case: [],
                existing_test_suite: '',
                existing_gmock_def: [],
                existing_cpp_stub_def: [],
                interface_definitions: interfaceDefinitions,
                source_class_constructor_method: constructorsMethod,
                source_class_name_lower: classNameLower,
                init_head_macro: '',
                gmock_str: gmockStr,
                cppstub_str: cppstubStr,
                source_class_fields: classFields,
                include_statement: '',
                using_namespace: usingNamespace,
                other_str: otherStr,
            };
            const end = Date.now(); // 记录结束时间
            const executionTime = end - start; // 计算执行时间
            Logger.info(`getHarmonyCppContext success time cost: ${executionTime}ms.`);
            // 计算可以留给高耗时函数的执行时间，预留200ms
            const remainingTime = utcoreTimeout - executionTime - RESERVE_TIME_MS;
            const restart = Date.now(); // 记录开始时间
            const harmonyCppPromptContextIncludeReferences =
                await this.getHarmonyCppContextByreferencesTimeout(document, functionInfo,
                    unittestsDir,
                    definitionInFunction,
                    gmockStr,
                    cppstubStr,
                    harmonyCppPromptContext,
                    remainingTime);

            const reend = Date.now(); // 记录结束时间
            const reexecutionTime = reend - restart; // 计算执行时间
            Logger.info(`getHarmonyCppContextByreferencesTimeout end time cost: ${reexecutionTime}ms.`);
            return harmonyCppPromptContextIncludeReferences || harmonyCppPromptContext;
        } catch (error) {
            const end = Date.now(); // 记录结束时间
            const executionTime = end - start; // 计算执行时间
            Logger.error(`getHarmonyCppContext err time cost: ${executionTime}ms. err :${error}`);
            return null;
        }
    }

    /**
     * 通过引用超时获取Harmony C++上下文
     * @param document 文档对象
     * @param functionInfo 函数信息
     * @param unittestsDir 单元测试目录
     * @param definitionInFunction 函数内定义
     * @param gmockStr GMock字符串
     * @param cppstubStr C++存根字符串
     * @param harmonyCppPromptContext 提示上下文
     * @param remainingTime 剩余时间
     * @returns 更新后的提示上下文
     */
    private static async getHarmonyCppContextByreferencesTimeout(
        document: vscode.TextDocument,
        functionInfo: FunctionInfo,
        unittestsDir: string,
        definitionInFunction: DefsInFunc,
        gmockStr: string,
        cppstubStr: string,
        harmonyCppPromptContext: HarmonyCppPromptContext,
        remainingTime: number
    ): Promise<HarmonyCppPromptContext | null> {
        Logger.info(`getHarmonyCppContextByreferencesTimeout start .the maximum available time : ${remainingTime}ms.`);
        if (remainingTime <= 0) {
            return null;
        }
        try {
            const promptPromise = this.getHarmonyCppContextByreferences(document,
                functionInfo,
                unittestsDir,
                definitionInFunction,
                gmockStr,
                cppstubStr,
                harmonyCppPromptContext);
            await Promise.race([promptPromise, waitForTimeout(remainingTime)]);
            if (!promptPromise) {
                return null;
            }
            Logger.info(`getHarmonyCppContextByreferencesTimeout success`);
            return promptPromise;
        } catch (err) {
            Logger.error(`getHarmonyCppContextByreferencesTimeout This request was aborted because it took more than ${remainingTime} ms`);
            return null;
        }
    }

    /**
     * 通过引用获取Harmony C++上下文
     * @param document 文档对象
     * @param functionInfo 函数信息
     * @param unittestsDir 单元测试目录
     * @param definitionInFunction 函数内定义
     * @param gmockStr GMock字符串
     * @param cppstubStr C++存根字符串
     * @param harmonyCppPromptContext 提示上下文
     * @returns 更新后的提示上下文
     */
    private static async getHarmonyCppContextByreferences(
        document: vscode.TextDocument,
        functionInfo: FunctionInfo,
        unittestsDir: string,
        definitionInFunction: DefsInFunc,
        gmockStr: string,
        cppstubStr: string,
        harmonyCppPromptContext: HarmonyCppPromptContext
    ): Promise<HarmonyCppPromptContext | null> {
        const { includeStr, filterReferences } = await CxxCustomizationProcessor.getIncludeStatment(document, definitionInFunction, functionInfo);
        const { testCases, testSuite, gMock, cppStub } = await CxxCustomizationProcessor.getUTTest(document, unittestsDir, functionInfo.sourceFunc?.position);
        const headMacro = CxxCustomizationProcessor.getHeadMacroStr(gmockStr, cppstubStr, includeStr, filterReferences);
        return {
            ...harmonyCppPromptContext,
            existing_test_case: testCases,
            existing_test_suite: testSuite,
            existing_gmock_def: gMock,
            existing_cpp_stub_def: cppStub,
            init_head_macro: headMacro,
            include_statement: includeStr
        };
    }

    /**
     * 获取基础通用C++上下文
     * @param document 文档对象
     * @param functionInfo 函数信息
     * @param range 范围
     * @param rowInfo 是否包含行信息
     * @returns 基础上下文
     */
    private static async getBaseCommonCppContext(document: vscode.TextDocument, functionInfo: FunctionInfo, range: vscode.Range, rowInfo = false): Promise<BaseCommonCppContext> {
        const start = Date.now(); // 记录开始时间
        let commonContext: BaseCommonCppContext = {
            language: 'cpp',
            ide: vscode.env.appName || 'VSCode',
            code: FunctionCodeProcessor.extract(functionInfo.code || ""),
            origin_code: functionInfo.code || "",
            cls: functionInfo.sourceClassName || "",
            source_method_file_path: document.fileName,
            source_method_signature: functionInfo.signature,
            source_method_name: functionInfo.sourceFuncName || "",
        };
        if (rowInfo) {
            commonContext.start_row = range.start.line + 1;
            commonContext.end_row = range.end.line + 1;
        }
        const end = Date.now(); // 记录结束时间
        const executionTime = end - start; // 计算执行时间
        Logger.info(`getBaseCommonCppContext success time cost: ${executionTime}ms.`);
        return commonContext;
    }





    // /**
    //  * 生成单元测试的主要方法
    //  * @param verticalDiffManager 垂直差异管理器
    //  * @param llmFactory LLM工厂
    //  * @param context 扩展上下文
    //  */
    // public static async generateUnitTest(
    //     verticalDiffManager: VerticalDiffManager,
    //     llmFactory: LLMFactory,
    //     context: vscode.ExtensionContext
    // ): Promise<void> {
    //     try {
    //         // 检查登录状态
    //         const isLoggedIn = await checkLoginStatus();
    //         if (!isLoggedIn) {
    //             vscode.window.showErrorMessage('请先登录后再使用此功能');
    //             return;
    //         }

    //         // 获取当前编辑器
    //         const editor = vscode.window.activeTextEditor;
    //         if (!editor) {
    //             vscode.window.showErrorMessage('请打开一个文件后再使用此功能');
    //             return;
    //         }

    //         const document = editor.document;
    //         const position = editor.selection.active;

    //         // 获取配置
    //         const config = vscode.workspace.getConfiguration('harmonypilot');
    //         const testDirectory = config.get<string>('unitTestDirectory', './tests');
    //         const timeout = config.get<number>('unitTestTimeout', 30000);

    //         // 显示进度
    //         await vscode.window.withProgress({
    //             location: vscode.ProgressLocation.Notification,
    //             title: "生成单元测试",
    //             cancellable: true
    //         }, async (progress, token) => {
    //             progress.report({ increment: 0, message: "分析代码..." });

    //             // 调用terminalDTCxxCustomization获取上下文
    //             const context = await this.terminalDTCxxCustomization(document, position, testDirectory, timeout);
                
    //             if (!context) {
    //                 vscode.window.showErrorMessage('无法分析代码，请检查代码格式');
    //                 return;
    //             }

    //             progress.report({ increment: 50, message: "生成测试代码..." });

    //             // 使用LLM生成测试代码
    //             const llm = llmFactory.getLLM();
    //             const testCode = await this.generateTestCodeWithLLM(llm, context, token);

    //             progress.report({ increment: 30, message: "保存测试文件..." });

    //             // 保存测试文件
    //             await this.saveTestFile(document, testCode, testDirectory);

    //             progress.report({ increment: 20, message: "完成" });

    //             vscode.window.showInformationMessage('单元测试生成完成！');
    //         });

    //     } catch (error) {
    //         Logger.error(`生成单元测试时出错: ${error}`);
    //         vscode.window.showErrorMessage(`生成单元测试时出错: ${error}`);
    //     }
    // }

//     /**
//      * 使用LLM生成测试代码
//      * @param llm LLM实例
//      * @param context 上下文
//      * @param token 取消令牌
//      * @returns 测试代码
//      */
//     private static async generateTestCodeWithLLM(
//         llm: BaseLLM,
//         context: any,
//         token?: vscode.CancellationToken
//     ): Promise<string> {
//         try {
//             const prompt = `请为以下C++函数生成单元测试代码：

// 函数信息：
// ${JSON.stringify(context, null, 2)}

// 请生成完整的单元测试代码，包括：
// 1. 必要的头文件包含
// 2. 测试用例设置
// 3. 各种边界条件测试
// 4. Mock对象的使用（如果需要）
// 5. 断言验证

// 请确保测试代码可以直接编译和运行。`;

//             const response = await llm._streamChat(prompt, new AbortController().signal);
//             return response || '// 无法生成测试代码';
//         } catch (error) {
    //             Logger.error(`LLM生成测试代码时出错: ${error}`);
//             return '// 生成测试代码时出错';
//         }
//     }

    // /**
    //  * 保存测试文件
    //  * @param document 原始文档
    //  * @param testCode 测试代码
    //  * @param testDirectory 测试目录
    //  */
    // private static async saveTestFile(
    //     document: vscode.TextDocument,
    //     testCode: string,
    //     testDirectory: string
    // ): Promise<void> {
    //     try {
    //         // 获取文件信息
    //         const fileName = path.basename(document.fileName || 'unknown');
    //         const testFileName = fileName.replace(/\.(cpp|cc|c)$/, '_test.cpp');
    //         const testFilePath = path.join(testDirectory, testFileName);

    //         // 确保测试目录存在
    //         const fullTestDir = path.resolve(testDirectory);
    //         if (!fs.existsSync(fullTestDir)) {
    //             fs.mkdirSync(fullTestDir, { recursive: true });
    //         }

    //         // 保存测试文件
    //         fs.writeFileSync(testFilePath, testCode, 'utf8');

    //         // 打开测试文件
    //         const testDoc = await vscode.workspace.openTextDocument(testFilePath);
    //         await vscode.window.showTextDocument(testDoc);

    //         Logger.info(`测试文件已保存到: ${testFilePath}`);
    //     } catch (error) {
    //         Logger.error(`保存测试文件时出错: ${error}`);
    //         throw error;
    //     }
    // }
}
